﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using Newtonsoft.Json;

namespace Koala.Pro.Common.Extension
{
    public static class StringExtensions
    {
        private static MD5CryptoServiceProvider s_md5;

        public static string ToJson(this object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.None);
        }

        public static T ConvertTo<T>(this IConvertible convertibleValue)
        {
            if (convertibleValue == null)
            {
                return default(T);
            }
            if (!typeof(T).IsGenericType)
            {
                return (T)Convert.ChangeType(convertibleValue, typeof(T));
            }
            if (typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                return (T)Convert.ChangeType(convertibleValue, Nullable.GetUnderlyingType(typeof(T)));
            }
            throw new InvalidCastException($"Invalid cast from type \"{convertibleValue.GetType().FullName}\" to type \"{typeof(T).FullName}\".");
        }

        public static DateTime ToDateTime(this string str)
        {
            str = ConvertHelper.ConvertToDBC(str);
            DateTime result = Convert.ToDateTime("1900-1-1");
            DateTime.TryParse(str, out result);
            return result;
        }

        public static int ToInt32(this string str, int defaultValue = 0)
        {
            str = ConvertHelper.ConvertToDBC(str);
            int.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static int ToInt16(this string str, short defaultValue = 0)
        {
            str = ConvertHelper.ConvertToDBC(str);
            short.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static long ToInt64(this string str, long defaultValue = 0L)
        {
            str = ConvertHelper.ConvertToDBC(str);
            long.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static ulong ToUInt64(this string str, ulong defaultValue = 0uL)
        {
            str = ConvertHelper.ConvertToDBC(str);
            ulong.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static uint ToUInt32(this string str, uint defaultValue = 0u)
        {
            str = ConvertHelper.ConvertToDBC(str);
            uint.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static ushort ToUInt16(this string str, ushort defaultValue = 0)
        {
            str = ConvertHelper.ConvertToDBC(str);
            ushort.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static byte ToByte(this string str, byte defaultValue = 0)
        {
            str = ConvertHelper.ConvertToDBC(str);
            byte.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static double ToDouble(this string str, double defaultValue = 0.0)
        {
            str = ConvertHelper.ConvertToDBC(str);
            double.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static decimal ToDecimal(this string str, decimal defaultValue = 0m)
        {
            str = ConvertHelper.ConvertToDBC(str);
            decimal.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static float ToFloat(this string str, float defaultValue = 0f)
        {
            str = ConvertHelper.ConvertToDBC(str);
            float.TryParse(str, out defaultValue);
            return defaultValue;
        }

        public static bool ToBoolean(this string str)
        {
            str = ConvertHelper.ConvertToDBC(str);
            string text = str.ToLower();
            if (text != null)
            {
                switch (text.Length)
                {
                    case 1:
                        {
                            char c = text[0];
                            if ((uint)c <= 102u)
                            {
                                if (c != '0')
                                {
                                    if (c == '1')
                                    {
                                        goto IL_00d0;
                                    }
                                    if (c != 'f')
                                    {
                                        break;
                                    }
                                }
                            }
                            else if (c != 'n')
                            {
                                if (c != 't' && c != 'y')
                                {
                                    break;
                                }
                                goto IL_00d0;
                            }
                            goto IL_00d4;
                        }
                    case 2:
                        {
                            char c = text[0];
                            if (c != '-')
                            {
                                if (c != 'n' || !(text == "no"))
                                {
                                    break;
                                }
                                goto IL_00d4;
                            }
                            if (!(text == "-1"))
                            {
                                break;
                            }
                            goto IL_00d0;
                        }
                    case 4:
                        if (!(text == "true"))
                        {
                            break;
                        }
                        goto IL_00d0;
                    case 3:
                        if (!(text == "yes"))
                        {
                            break;
                        }
                        goto IL_00d0;
                    case 5:
                        {
                            if (!(text == "false"))
                            {
                                break;
                            }
                            goto IL_00d4;
                        }
                    IL_00d0:
                        return true;
                    IL_00d4:
                        return false;
                }
            }
            return false;
        }

        public static List<T> ToDelimitedList<T>(this string value, string delimiter)
        {
            if (value == null)
            {
                return new List<T>();
            }
            return (from x in value.Split(new string[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries)
                    select (T)Convert.ChangeType(x.Trim(), typeof(T))).ToList();
        }

        public static List<T> ToDelimitedList<T>(this string value, string delimiter, Func<string, T> converter)
        {
            if (value == null)
            {
                return new List<T>();
            }
            return value.Split(new string[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries).Select(converter).ToList();
        }

        public static IEnumerable<string> SplitEvery(this string value, int length)
        {
            int index;
            for (index = 0; index + length < value.Length; index += length)
            {
                yield return value.Substring(index, length);
            }
            if (index < value.Length)
            {
                yield return value.Substring(index, value.Length - index);
            }
        }

        public static string UriCombine(this string val, string append)
        {
            if (string.IsNullOrEmpty(val))
            {
                return append;
            }
            if (string.IsNullOrEmpty(append))
            {
                return val;
            }
            return val.TrimEnd(new char[1] { '/' }) + "/" + append.TrimStart(new char[1] { '/' });
        }

        public static string PathCombine(this string val, string path2)
        {
            if (Path.IsPathRooted(path2))
            {
                path2 = path2.TrimStart(new char[1] { Path.DirectorySeparatorChar });
                path2 = path2.TrimStart(new char[1] { Path.AltDirectorySeparatorChar });
            }
            return Path.Combine(val, path2);
        }

        public static bool IsValidEmailAddress(this string email)
        {
            if (string.IsNullOrEmpty(email))
            {
                return false;
            }
            return new Regex("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,6}$").IsMatch(email);
        }

        public static bool IsValidUrl(this string url)
        {
            return new Regex("^(https?://)?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?(([0-9]{1,3}\\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z](\\.[a-z]{2,6})?)(:[0-9]{1,5})?((/?)|(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$").IsMatch(url);
        }

        public static bool IsValidURI(this string val)
        {
            if (string.IsNullOrEmpty(val))
            {
                return false;
            }
            return Uri.IsWellFormedUriString(val, UriKind.Absolute);
        }

        public static bool UrlAvailable(this string httpUrl)
        {
            if (!httpUrl.StartsWith("http://") || !httpUrl.StartsWith("https://"))
            {
                httpUrl = "http://" + httpUrl;
            }
            try
            {
                HttpWebRequest obj = (HttpWebRequest)WebRequest.Create(httpUrl);
                obj.Method = "GET";
                obj.ContentType = "application/x-www-form-urlencoded";
                _ = (HttpWebResponse)obj.GetResponse();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static string Reverse(this string input)
        {
            string result = string.Empty;
            if (input != null)
            {
                char[] array = input.ToCharArray();
                Array.Reverse((Array)array);
                result = new string(array);
            }
            return result;
        }

        public static string Reduce(this string s, int count, string endings)
        {
            if (count < endings.Length)
            {
                throw new Exception("Failed to reduce to less then endings length.");
            }
            int length = s.Length;
            int num = length;
            if (endings != null)
            {
                num += endings.Length;
            }
            if (count > length)
            {
                return s;
            }
            s = s.Substring(0, length - num + count);
            if (endings != null)
            {
                s += endings;
            }
            return s;
        }

        public static string Replace(this string str, string find, string replacement, bool caseSensitive)
        {
            if (caseSensitive)
            {
                return Regex.Replace(str, find, replacement);
            }
            return Regex.Replace(str, find, replacement, RegexOptions.IgnoreCase);
        }

        public static string RemoveSpaces(this string s)
        {
            s = s.Trim();
            s = s.Replace(" ", "");
            return s;
        }

        public static string RemoveFinalChar(this string s)
        {
            if (s.Length > 1)
            {
                s = s.Substring(0, s.Length - 1);
            }
            return s;
        }

        public static string RemoveFinalComma(this string s)
        {
            if (s.Trim().Length > 0)
            {
                int num = s.LastIndexOf(",");
                if (num > 0)
                {
                    s = s.Substring(0, s.Length - (s.Length - num));
                }
            }
            return s;
        }

        public static string Repeat(this string s, int repeatCount)
        {
            string text = string.Empty;
            for (int i = 0; i < repeatCount; i++)
            {
                text += s;
            }
            return text;
        }

        public static bool IsNumber(this string s, bool floatpoint)
        {
            string s2 = s.RemoveSpaces();
            double result;
            if (floatpoint)
            {
                return double.TryParse(s2, NumberStyles.Any, Thread.CurrentThread.CurrentUICulture, out result);
            }
            int result2;
            return int.TryParse(s2, out result2);
        }

        public static bool IsNumberOnly(this string s, bool floatpoint)
        {
            s = s.Trim();
            if (s.Length == 0)
            {
                return false;
            }
            string text = s;
            foreach (char c in text)
            {
                if (!char.IsDigit(c) && (!floatpoint || (c != '.' && c != ',')))
                {
                    return false;
                }
            }
            return true;
        }

        public static string RemoveDiacritics(this string s)
        {
            string text = s.Normalize(NormalizationForm.FormD);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < text.Length; i++)
            {
                if (CharUnicodeInfo.GetUnicodeCategory(text[i]) != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(text[i]);
                }
            }
            return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
        }

        public static string Nl2Br(this string s)
        {
            return s.Replace("\r\n", "<br />").Replace("\n", "<br />");
        }

        public static string MD5(this string s)
        {
            if (s_md5 == null)
            {
                s_md5 = new MD5CryptoServiceProvider();
            }
            byte[] bytes = Encoding.Default.GetBytes(s);
            return BitConverter.ToString(s_md5.ComputeHash(bytes)).Replace("-", "").ToLower();
        }

        public static string CaseInsenstiveReplace(this string val, char charToReplace, char replacement)
        {
            return new Regex(charToReplace.ToString(), RegexOptions.IgnoreCase | RegexOptions.Multiline).Replace(val, replacement.ToString());
        }

        public static string CaseInsenstiveReplace(this string val, string stringToReplace, string replacement)
        {
            return new Regex(stringToReplace, RegexOptions.IgnoreCase | RegexOptions.Multiline).Replace(val, replacement);
        }

        public static string RemoveWords(this string val, params string[] filterWords)
        {
            return val.MaskWords('\0', filterWords);
        }

        public static string MaskWords(this string val, char mask, params string[] filterWords)
        {
            string text = ((mask == '\0') ? string.Empty : mask.ToString());
            string text2 = text;
            foreach (string text3 in filterWords)
            {
                Regex regex = new Regex(text3, RegexOptions.IgnoreCase | RegexOptions.Multiline);
                if (text.Length > 0)
                {
                    for (int j = 1; j < text3.Length; j++)
                    {
                        text2 += text;
                    }
                }
                val = regex.Replace(val, text2);
                text2 = text;
            }
            return val;
        }

        public static string WordWrap(this string val, int charCount)
        {
            return val.WordWrap(charCount, cutOff: false, Environment.NewLine);
        }

        public static string WordWrap(this string val, int charCount, bool cutOff)
        {
            return val.WordWrap(charCount, cutOff, Environment.NewLine);
        }

        private static string WordWrap(this string val, int charCount, bool cutOff, string breakText)
        {
            StringBuilder stringBuilder = new StringBuilder(val.Length + 100);
            int i = 0;
            if (cutOff)
            {
                for (; i < val.Length; i += charCount)
                {
                    if (val.Length > i + charCount)
                    {
                        stringBuilder.Append(val.Substring(i, charCount));
                        stringBuilder.Append(breakText);
                    }
                    else
                    {
                        stringBuilder.Append(val.Substring(i));
                    }
                }
            }
            else
            {
                string[] array = val.Split(new char[1] { ' ' });
                for (int j = 0; j < array.Length; j++)
                {
                    i += array[j].Length + 1;
                    if (j != 0 && i > charCount)
                    {
                        stringBuilder.Append(breakText);
                        i = 0;
                    }
                    stringBuilder.Append(array[j] + " ");
                }
            }
            return stringBuilder.ToString().TrimEnd(Array.Empty<char>());
        }

        public static string ToCSV(this IEnumerable<string> val, bool insertSpaces)
        {
            if (insertSpaces)
            {
                return string.Join(", ", val.ToArray());
            }
            return string.Join(",", val.ToArray());
        }

        public static string ToCSV(this IEnumerable<char> val, bool insertSpaces)
        {
            List<string> list = new List<string>();
            foreach (char item in val)
            {
                list.Add(item.ToString());
            }
            if (insertSpaces)
            {
                return string.Join(", ", list.ToArray());
            }
            return string.Join(",", list.ToArray());
        }

        public static IEnumerable<string> ListFromCSV(this string val)
        {
            string[] array = val.Split(new char[1] { ',' });
            string[] array2 = array;
            for (int i = 0; i < array2.Length; i++)
            {
                array2[i].Trim();
            }
            return new List<string>(array);
        }

        public static bool IsMatch(this string value, string pattern, bool isContains = true)
        {
            if (value == null)
            {
                return false;
            }
            if (!isContains)
            {
                return Regex.Match(value, pattern).Success;
            }
            return Regex.IsMatch(value, pattern);
        }

        public static string Match(this string value, string pattern)
        {
            if (value == null)
            {
                return null;
            }
            return Regex.Match(value, pattern).Value;
        }

        public static string ReplaceRegex(this string value, string pattern, string replacement)
        {
            if (value == null)
            {
                return null;
            }
            return Regex.Replace(value, pattern, replacement);
        }

        public static IEnumerable<string> Matches(this string value, string pattern)
        {
            if (value == null)
            {
                return new string[0];
            }
            return from Match match in Regex.Matches(value, pattern)
                   select match.Value;
        }

        public static string MatchFirstNumber(this string value)
        {
            MatchCollection matchCollection = Regex.Matches(value, "\\d+");
            if (matchCollection.Count == 0)
            {
                return string.Empty;
            }
            return matchCollection[0].Value;
        }

        public static string MatchLastNumber(this string value)
        {
            MatchCollection matchCollection = Regex.Matches(value, "\\d+");
            if (matchCollection.Count == 0)
            {
                return string.Empty;
            }
            return matchCollection[matchCollection.Count - 1].Value;
        }

        public static IEnumerable<string> MatchNumbers(this string value)
        {
            return value.Matches("\\d+");
        }

        public static bool IsMatchNumber(this string value)
        {
            return value.IsMatch("\\d");
        }

        public static bool IsMatchNumber(this string value, int length)
        {
            return new Regex("^\\d{" + length + "}$").IsMatch(value);
        }

        public static string Substring(this string source, string startString, params string[] endStrings)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                return string.Empty;
            }
            int num = 0;
            if (!string.IsNullOrEmpty(startString))
            {
                num = source.IndexOf(startString, StringComparison.OrdinalIgnoreCase);
                if (num < 0)
                {
                    throw new InvalidOperationException($"在源字符串中无法找到“{startString}”的子串位置");
                }
                num += startString.Length;
            }
            int num2 = source.Length;
            endStrings = endStrings.OrderByDescending((string m) => m.Length).ToArray();
            string[] array = endStrings;
            foreach (string value in array)
            {
                if (string.IsNullOrEmpty(value))
                {
                    num2 = source.Length;
                    break;
                }
                num2 = source.IndexOf(value, num, StringComparison.OrdinalIgnoreCase);
                if (num2 >= 0 && num2 >= num)
                {
                    break;
                }
            }
            if (num2 < 0 || num2 < num)
            {
                throw new InvalidOperationException($"在源字符串中无法找到“{endStrings.ExpandAndToString()}”的子串位置");
            }
            int length = num2 - num;
            return source.Substring(num, length);
        }

        public static string Substring2(this string source, string startString, string endString)
        {
            return source.Substring2(startString, endString, containsEmpty: false);
        }

        public static string Substring2(this string source, string startString, string endString, bool containsEmpty)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                return string.Empty;
            }
            string arg = (containsEmpty ? "\\s\\S" : "\\S");
            string result = source.Match($"(?<={startString})([{arg}]+?)(?={endString})");
            if (!string.IsNullOrWhiteSpace(source))
            {
                return result;
            }
            return null;
        }

        public static bool IsEmail(this string value)
        {
            return value.IsMatch("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$");
        }

        public static bool IsIpAddress(this string value)
        {
            return value.IsMatch("^((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))$");
        }

        public static bool IsNumeric(this string value)
        {
            return value.IsMatch("^\\-?[0-9]+$");
        }

        public static bool IsUnicode(this string value)
        {
            return value.IsMatch("^[\\u4E00-\\u9FA5\\uE815-\\uFA29]+$");
        }

        public static bool IsUrl(this string value)
        {
            try
            {
                if (value.IsNullOrEmpty() || Enumerable.Contains(value, ' '))
                {
                    return false;
                }
                new Uri(value);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool IsIdentityCardId(this string value)
        {
            if (value.Length != 15 && value.Length != 18)
            {
                return false;
            }
            DateTime result;
            Regex regex;
            string[] array;
            if (value.Length == 15)
            {
                regex = new Regex("^(\\d{6})(\\d{2})(\\d{2})(\\d{2})(\\d{3})_");
                if (!regex.Match(value).Success)
                {
                    return false;
                }
                array = regex.Split(value);
                return DateTime.TryParse(string.Format("{0}-{1}-{2}", "19" + array[2], array[3], array[4]), out result);
            }
            regex = new Regex("^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9Xx])$");
            if (!regex.Match(value).Success)
            {
                return false;
            }
            array = regex.Split(value);
            if (!DateTime.TryParse($"{array[2]}-{array[3]}-{array[4]}", out result))
            {
                return false;
            }
            string[] array2 = (from m in value.ToCharArray()
                               select m.ToString()).ToArray();
            int[] array3 = new int[17]
            {
            7, 9, 10, 5, 8, 4, 2, 1, 6, 3,
            7, 9, 10, 5, 8, 4, 2
            };
            int num = 0;
            for (int i = 0; i < 17; i++)
            {
                int num2 = int.Parse(array2[i]);
                num += num2 * array3[i];
            }
            int index = num % 11;
            string text = "10X98765432".ToCharArray().ElementAt(index).ToString();
            return array2.Last().ToUpper() == text;
        }

        public static bool IsMobileNumber(this string value, bool isRestrict = false)
        {
            string pattern = (isRestrict ? "^[1][3-8]\\d{9}$" : "^[1]\\d{10}$");
            return value.IsMatch(pattern);
        }

        public static string ToSingular(this string word)
        {
            Regex regex = new Regex("(?<keep>[^aeiou])ies$");
            Regex regex2 = new Regex("(?<keep>[aeiou]y)s$");
            Regex regex3 = new Regex("(?<keep>[sxzh])es$");
            Regex regex4 = new Regex("(?<keep>[^sxzhyu])s$");
            if (regex.IsMatch(word))
            {
                return regex.Replace(word, "${keep}y");
            }
            if (regex2.IsMatch(word))
            {
                return regex2.Replace(word, "${keep}");
            }
            if (regex3.IsMatch(word))
            {
                return regex3.Replace(word, "${keep}");
            }
            if (regex4.IsMatch(word))
            {
                return regex4.Replace(word, "${keep}");
            }
            return word;
        }

        public static string ToPlural(this string word)
        {
            Regex regex = new Regex("(?<keep>[^aeiou])y$");
            Regex regex2 = new Regex("(?<keep>[aeiou]y)$");
            Regex regex3 = new Regex("(?<keep>[sxzh])$");
            Regex regex4 = new Regex("(?<keep>[^sxzhy])$");
            if (regex.IsMatch(word))
            {
                return regex.Replace(word, "${keep}ies");
            }
            if (regex2.IsMatch(word))
            {
                return regex2.Replace(word, "${keep}s");
            }
            if (regex3.IsMatch(word))
            {
                return regex3.Replace(word, "${keep}es");
            }
            if (regex4.IsMatch(word))
            {
                return regex4.Replace(word, "${keep}s");
            }
            return word;
        }

        public static bool IsImageFile(this string filename)
        {
            if (!File.Exists(filename))
            {
                return false;
            }
            byte[] array = File.ReadAllBytes(filename);
            if (array.Length == 0)
            {
                return false;
            }
            switch (BitConverter.ToUInt16(array, 0))
            {
                case 18759:
                case 19778:
                case 20617:
                case 55551:
                    return true;
                default:
                    return false;
            }
        }

        public static int TextLength(this string value)
        {
            ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
            int num = 0;
            byte[] bytes = aSCIIEncoding.GetBytes(value);
            for (int i = 0; i < bytes.Length; i++)
            {
                num = ((bytes[i] != 63) ? (num + 1) : (num + 2));
            }
            return num;
        }

        public static string[] Split(this string value, string strSplit, bool removeEmptyEntries = false)
        {
            return value.Split(new string[1] { strSplit }, removeEmptyEntries ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
        }

        public static string AddUrlQuery(this string url, params string[] queries)
        {
            foreach (string text in queries)
            {
                if (!url.Contains("?"))
                {
                    url += "?";
                }
                else if (!url.EndsWith("&"))
                {
                    url += "&";
                }
                url += text;
            }
            return url;
        }

        public static string GetUrlQuery(this string url, string key)
        {
            string query = new Uri(url).Query;
            if (query.IsNullOrEmpty())
            {
                return string.Empty;
            }
            query = query.TrimStart(new char[1] { '?' });
            Dictionary<string, string> dictionary = (from m in query.Split("&", removeEmptyEntries: true)
                                                     let strs = Split(m, "=")
                                                     select new KeyValuePair<string, string>(strs[0], strs[1])).ToDictionary((KeyValuePair<string, string> m) => m.Key, (KeyValuePair<string, string> m) => m.Value);
            if (dictionary.ContainsKey(key))
            {
                return dictionary[key];
            }
            return string.Empty;
        }

        public static string AddHashFragment(this string url, string query)
        {
            if (!url.Contains("#"))
            {
                url += "#";
            }
            return url + query;
        }

        public static byte[] ToBytes(this string value, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            return encoding.GetBytes(value);
        }

        public static string ToString2(this byte[] bytes, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            return encoding.GetString(bytes);
        }

        public static string ToBase64String(this byte[] bytes)
        {
            return Convert.ToBase64String(bytes);
        }

        public static int Byte8ToInt(this byte[] bytes)
        {
            if (bytes[0] == 0 && bytes[1] == 0)
            {
                Array.Reverse((Array)bytes);
            }
            return BitConverter.ToInt32(bytes, 0);
        }

        public static long BytesToLong(this byte[] bytes)
        {
            if (bytes[0] == 0 && bytes[1] == 0)
            {
                Array.Reverse((Array)bytes);
            }
            return BitConverter.ToInt64(bytes, 0);
        }

        private static byte[] IntToBytes(int number)
        {
            return BitConverter.GetBytes(number);
        }

        private static byte[] LongToBytes(long number)
        {
            return BitConverter.GetBytes(number);
        }

        public static string ToBase64String(this string source, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            return Convert.ToBase64String(encoding.GetBytes(source));
        }

        public static string FromBase64String(this string base64String, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            byte[] bytes = Convert.FromBase64String(base64String);
            return encoding.GetString(bytes);
        }

        public static string ToUrlDecode(this string source)
        {
            return HttpUtility.UrlDecode(source);
        }

        public static string ToUrlEncode(this string source)
        {
            return HttpUtility.UrlEncode(source);
        }

        public static string ToHtmlDecode(this string source)
        {
            return HttpUtility.HtmlDecode(source);
        }

        public static string ToHtmlEncode(this string source)
        {
            return HttpUtility.HtmlEncode(source);
        }

        public static string ToHexString(this string source, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            return encoding.GetBytes(source).ToHexString();
        }

        public static string FromHexString(this string hexString, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            byte[] bytes = hexString.ToHexBytes();
            return encoding.GetString(bytes);
        }

        public static byte[] ToHexBytes(this string hexString)
        {
            hexString = hexString ?? "";
            hexString = hexString.Replace(" ", "");
            byte[] array = new byte[hexString.Length / 2];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }
            return array;
        }

        public static string ToUnicodeString(this string source)
        {
            return new Regex("[^\\u0000-\\u00ff]").Replace(source, (Match m) => $"\\u{(short)m.Value[0]:x4}");
        }

        public static string FromUnicodeString(this string source)
        {
            short result;
            return new Regex("\\\\u([0-9a-fA-F]{4})", RegexOptions.Compiled).Replace(source, (Match m) => short.TryParse(m.Groups[1].Value, NumberStyles.HexNumber, CultureInfo.InstalledUICulture, out result) ? (((char)result).ToString() ?? "") : m.Value);
        }

        public static string UpperToLowerAndSplit(this string str, string splitStr = "-")
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            List<string> list = new List<string>();
            while (str.Length > 0)
            {
                char c = str.FirstOrDefault(char.IsUpper);
                if (c == '\0')
                {
                    list.Add(str);
                    break;
                }
                int num = str.IndexOf(c);
                if (num < 0)
                {
                    return str;
                }
                if (num > 0)
                {
                    string item = str.Substring(0, num);
                    list.Add(item);
                    str = str.Substring(num, str.Length - num);
                }
                else
                {
                    str = char.ToLower(str[0]) + str.Substring(1, str.Length - 1);
                }
            }
            return list.ExpandAndToString(splitStr);
        }

        public static string LowerFirstChar(this string str)
        {
            if (string.IsNullOrEmpty(str) || !char.IsUpper(str[0]))
            {
                return str;
            }
            if (str.Length == 1)
            {
                return char.ToLower(str[0]).ToString();
            }
            return char.ToLower(str[0]) + str.Substring(1, str.Length - 1);
        }

        public static string UpperFirstChar(this string str)
        {
            if (string.IsNullOrEmpty(str) || !char.IsLower(str[0]))
            {
                return str;
            }
            if (str.Length == 1)
            {
                return char.ToUpper(str[0]).ToString();
            }
            return char.ToUpper(str[0]) + str.Substring(1, str.Length - 1);
        }

        public static int LevenshteinDistance(this string source, string target, out double similarity, bool ignoreCase = false)
        {
            if (string.IsNullOrEmpty(source))
            {
                if (string.IsNullOrEmpty(target))
                {
                    similarity = 1.0;
                    return 0;
                }
                similarity = 0.0;
                return target.Length;
            }
            if (string.IsNullOrEmpty(target))
            {
                similarity = 0.0;
                return source.Length;
            }
            string text;
            string text2;
            if (ignoreCase)
            {
                text = source;
                text2 = target;
            }
            else
            {
                text = source.ToLower();
                text2 = source.ToLower();
            }
            int length = text.Length;
            int length2 = text2.Length;
            int[,] array = new int[length + 1, length2 + 1];
            for (int i = 0; i <= length; i++)
            {
                array[i, 0] = i;
            }
            for (int j = 1; j <= length2; j++)
            {
                array[0, j] = j;
            }
            for (int k = 1; k <= length; k++)
            {
                char c = text[k - 1];
                for (int l = 1; l <= length2; l++)
                {
                    if (c == text2[l - 1])
                    {
                        array[k, l] = array[k - 1, l - 1];
                    }
                    else
                    {
                        array[k, l] = Math.Min(array[k - 1, l - 1], Math.Min(array[k - 1, l], array[k, l - 1])) + 1;
                    }
                }
            }
            int num = Math.Max(length, length2);
            similarity = (double)(num - array[length, length2]) / (double)num;
            return array[length, length2];
        }

        public static double GetSimilarityWith(this string source, string target, bool ignoreCase = false)
        {
            if (string.IsNullOrEmpty(source) && string.IsNullOrEmpty(target))
            {
                return 1.0;
            }
            if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target))
            {
                return 0.0;
            }
            char[] array = source.ToCharArray();
            char[] array2 = target.ToCharArray();
            int num = array.Intersect(array2).Count();
            int num2 = array.Length - num;
            int num3 = array2.Length - num;
            return 2.0 * (double)num / (2.0 * (double)num + 1.0 * (double)num3 + 1.0 * (double)num2);
        }

        public static string ToPascalCase(this string original)
        {
            Regex regex = new Regex("[^_a-zA-Z0-9]");
            Regex regex2 = new Regex("(?<=\\s)");
            Regex startsWithLowerCaseChar = new Regex("^[a-z]");
            Regex firstCharFollowedByUpperCasesOnly = new Regex("(?<=[A-Z])[A-Z0-9]+$");
            Regex lowerCaseNextToNumber = new Regex("(?<=[0-9])[a-z]");
            Regex upperCaseInside = new Regex("(?<=[A-Z])[A-Z]+?((?=[A-Z][a-z])|(?=[0-9]))");
            return string.Concat(from w in regex.Replace(regex2.Replace(original, "_"), string.Empty).Split(new char[1] { '_' }, StringSplitOptions.RemoveEmptyEntries)
                                 select startsWithLowerCaseChar.Replace(w, (Match m) => m.Value.ToUpper()) into w
                                 select firstCharFollowedByUpperCasesOnly.Replace(w, (Match m) => m.Value.ToLower()) into w
                                 select lowerCaseNextToNumber.Replace(w, (Match m) => m.Value.ToUpper()) into w
                                 select upperCaseInside.Replace(w, (Match m) => m.Value.ToLower()));
        }

        public static string ToUnderLine(this string str, bool isToUpper = false)
        {
            if (str == null || str.Contains("_"))
            {
                return str;
            }
            if (isToUpper)
            {
                return string.Concat(str.Select((char x, int i) => (i <= 0 || !char.IsUpper(x)) ? x.ToString() : ("_" + x))).ToUpper();
            }
            return string.Concat(str.Select((char x, int i) => (i <= 0 || !char.IsUpper(x)) ? x.ToString() : ("_" + x))).ToLower();
        }
    }
}
